using Microsoft.Xna.Framework;

namespace tutFuelCellGame
{

    public enum CameraOperation
    {
        /// <summary>
        /// camera follows the object at a fixed distance
        /// </summary>
        chasing,
        /// <summary>
        /// camera stays where it is, but still looks at the object
        /// </summary>
        following
    }

    public class Camera
    {

        public Vector3 AvatarHeadOffset { get; set; }
        public Vector3 TargetOffset { get; set; }
        public Matrix ViewMatrix { get; set; }
        public Matrix ProjectionMatrix { get; set; }
        public float ChaseDistance { get; set; }
        public CameraOperation Operation { get; set; }

        /// <summary>
        /// Returns the Position of the camera. Gets updated during Update routine.
        /// </summary>
        public Vector3 Position { get { return _position; } }
        private Vector3 _position = Vector3.Zero;

        /// <summary>
        /// Constructs a chase camera
        /// </summary>
        public Camera()
        {
            ChaseDistance = 0f;
            TargetOffset = new Vector3(0, 2f, 0);
            
            TargetOffset = new Vector3(0, 3f, 0);
            ViewMatrix = Matrix.Identity;
            ProjectionMatrix = Matrix.Identity;

            InitCameraPositions();
        }

        private void InitCameraPositions()
        {
            cameraPositions = new Vector3[3];
            cameraPositions[0] = new Vector3(0, 5f, -11f);
            cameraPositions[1] = new Vector3(0, 4f, -7f);
            cameraPositions[2] = new Vector3(0, 25f, -35f);
            currentCameraPosition = -1;
            NextPosition();
        }

        public void Update(float avatarRotation, Vector3 avatarPosition, float aspectRatio)
        {

            AvatarHeadOffset = cameraPositions[currentCameraPosition];
            Matrix rotationMatrix = Matrix.CreateRotationY(avatarRotation);

            if (Operation == CameraOperation.chasing)
            {
                Vector3 transformedheadOffset = Vector3.Transform(AvatarHeadOffset + new Vector3(0, 0, -ChaseDistance),
                                                                  rotationMatrix);
                _position = avatarPosition + transformedheadOffset;
            }

            Vector3 transformedReference = Vector3.Transform(TargetOffset, rotationMatrix);
            Vector3 cameraTarget = avatarPosition + transformedReference;

            //Calculate the camera's view and projection 
            //matrices based on current values.
            ViewMatrix = Matrix.CreateLookAt(Position, cameraTarget, Vector3.Up);
            ProjectionMatrix = Matrix.CreatePerspectiveFieldOfView(
                    MathHelper.ToRadians(GameConstants.ViewAngle), aspectRatio,
                    GameConstants.NearClip, GameConstants.FarClip);

        }

        private Vector3[] cameraPositions;
        private int currentCameraPosition;

        public void NextPosition()
        {
            currentCameraPosition = ++currentCameraPosition % cameraPositions.Length;
        }
    }

}